﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;
using UnityEngine.Events;

[AddComponentMenu("UI/Behavior/PopAnimate")]
public class UIPopAnimate : MonoBehaviour
{

    // Start is called before the first frame update
    public enum ANIMATE_STATE
    {
        NONE,
        FADE,
        SCALE,
        SPREAD,
        ROTATE_X,
        ROTATE_Y,
        ROTATE_Z,
        MOVE_UP,
        MOVE_DOWN,
        MOVE_RIGHT,
        MOVE_LEFT,
    }

    [Header("=====  动画目标  =====")]
    [Tooltip("弹窗动画")]
    public Image darkImage;
    [Tooltip("动画播放的目标")]
    public GameObject content;

    [Header("=====  进入动画  =====")]
    [Tooltip("是否在一开始就播放动画")]
    public bool isAutoStartAnimate = true;
    public ANIMATE_STATE animatePopIn = ANIMATE_STATE.SCALE;
    public Ease easePopIn = Ease.InOutBack;
    [Range(0, 5)]
    public float speedPopIn = 0.5f;
    [Range(0, 1), Tooltip("播放动画前的初始值比例调整")]
    public float easeValuePopIn = 0.3f;

    [Header("=====  离开动画  =====")]
    [Tooltip("是否结束播放动画")]
    public bool isAutoEndAnimate = true;
    public ANIMATE_STATE animatePopOut = ANIMATE_STATE.SCALE;
    public Ease easePopOut = Ease.InOutBack;
    [Range(0, 5)]
    public float speedPopOut = 0.5f;
    [Range(0, 1), Tooltip("播放动画完成后的值比例调整")]
    public float easeValuePopOut = 0.3f;

    [Header("=====  自动销毁  =====")]
    public float delayStartTime = 0f;
    [Tooltip("自动播放延迟的时间")]
    public float delayEndTime = 0.5f;
    [Tooltip("动画播放完毕后是否直接销毁")]
    public bool isFadeOutDestroy = true;
    [Tooltip("动画播放完毕后是否隐藏 (方便回收设定)")]
    public bool isFadeOutDisable = false;

    // private CanvasGroup canvasGroup;

    [HideInInspector] public CanvasGroup canvasGroup;

    private System.Action callbackAction;

    private void Awake()
    {
        //标记 CanvasGroup 做好fade 的准备
        var group = GetComponent<CanvasGroup>();
        if (!group) group = gameObject.AddComponent<CanvasGroup>();
        canvasGroup = group;

        if (isAutoStartAnimate)
        {
            if (delayEndTime <= 0)
            {
                OnPlayAnimationIn();
            }
            else
            {
                canvasGroup.alpha = 0;
                Invoke("OnPlayAnimationIn", delayStartTime);
            }
        }
    }

    private void OnPlayAnimationIn()
    {
        var dark = darkImage;
        var obj = content;
        var speed = speedPopIn;
        float targetAlpha = 0;
        if (dark)
        {
            targetAlpha = dark.color.a;
            dark.color = new Color(dark.color.r, dark.color.g, dark.color.b, 0);
            dark.DOFade(targetAlpha, speed);
        }

        // fade CanvasGroup
        if (canvasGroup != null)
        {
            canvasGroup.alpha = 0;
            DOTween.To(() =>
            {
                return canvasGroup.alpha;
            }, x =>
            {
                canvasGroup.alpha = x;
            }, 1, speed).SetId(gameObject);
        }


        Tween tween;
        var a = easeValuePopIn;
        var rectTrans = obj.GetComponent<RectTransform>();
        var screenHeight = Screen.height * a;
        var screenWidth = Screen.width * a;
        Vector3 oldPos = Vector3.zero;
        switch (animatePopIn)
        {
            case ANIMATE_STATE.SCALE:
                obj.transform.localScale = new Vector3(1 - a, 1 - a, 1 - a);
                tween = obj.transform.DOScale(1.0f, speed).SetEase(easePopIn);
                break;
            case ANIMATE_STATE.SPREAD:
                obj.transform.localScale = new Vector3(a * 5 + 1, a * 5 + 1, a * 5 + 1);
                tween = obj.transform.DOScale(1.0f, speed).SetEase(easePopIn);
                break;
            case ANIMATE_STATE.ROTATE_X:
                obj.transform.localEulerAngles = new Vector3(360 * (a - 0.5f), 0, 0);
                tween = obj.transform.DOLocalRotate(new Vector3(0, 0, 0), speed, RotateMode.FastBeyond360).SetEase(easePopIn);
                break;
            case ANIMATE_STATE.ROTATE_Y:
                obj.transform.localEulerAngles = new Vector3(0, 360 * (a - 0.5f), 0);
                tween = obj.transform.DOLocalRotate(new Vector3(0, 0, 0), speed, RotateMode.FastBeyond360).SetEase(easePopIn);
                break;
            case ANIMATE_STATE.ROTATE_Z:
                obj.transform.localEulerAngles = new Vector3(0, 0, 360 * (a - 0.5f));
                tween = obj.transform.DOLocalRotate(new Vector3(0, 0, 0), speed, RotateMode.FastBeyond360).SetEase(easePopIn);
                break;
            case ANIMATE_STATE.MOVE_UP:
                rectTrans.localPosition = new Vector3(rectTrans.localPosition.x, rectTrans.localPosition.y - screenHeight, rectTrans.position.z);
                tween = rectTrans.DOLocalMoveY(oldPos.y, speed).SetEase(easePopIn);
                break;
            case ANIMATE_STATE.MOVE_DOWN:
                rectTrans.localPosition = new Vector3(rectTrans.localPosition.x, rectTrans.localPosition.y + screenHeight, rectTrans.position.z);
                tween = rectTrans.DOLocalMoveY(oldPos.y, speed).SetEase(easePopIn);
                break;
            case ANIMATE_STATE.MOVE_LEFT:
                rectTrans.localPosition = new Vector3(rectTrans.localPosition.x + screenWidth, rectTrans.localPosition.y, rectTrans.position.z);
                tween = rectTrans.DOLocalMoveX(oldPos.x, speed).SetEase(easePopIn);
                break;
            case ANIMATE_STATE.MOVE_RIGHT:
                rectTrans.localPosition = new Vector3(rectTrans.localPosition.x - screenWidth, rectTrans.localPosition.y, rectTrans.position.z);
                tween = rectTrans.DOLocalMoveX(oldPos.x, speed).SetEase(easePopIn);
                break;
            default:
                obj.transform.localScale = new Vector3(1, 1, 1);
                tween = obj.transform.DOScale(1.0f, speed).SetEase(easePopIn);
                break;
        }

        tween.SetId(this.gameObject);


        if (isAutoEndAnimate)
        {
            if (tween != null)
            {
                tween.onComplete += () =>
                {
                    Invoke("OnPlayAnimationOut", delayEndTime);
                };
            }

        }

    }


    private void OnPlayAnimationOut()
    {
        var dark = darkImage;
        var obj = content;
        var speed = speedPopOut;
        float targetAlpha = 0;
        if (dark) targetAlpha = dark.color.a;

        // fade CanvasGroup
        if (canvasGroup != null)
        {
            DOTween.To(() =>
                {
                    return canvasGroup.alpha;
                }, x =>
                {
                    canvasGroup.alpha = x;
                }, 0, speed).SetId(gameObject);
        }



        Tween tween;
        var a = easeValuePopOut;
        var rectTrans = obj.GetComponent<RectTransform>();
        var screenHeight = Screen.height * a;
        var screenWidth = Screen.width * a;

        switch (animatePopOut)
        {
            case ANIMATE_STATE.SCALE:
                tween = obj.transform.DOScale(1 - a, speed);
                break;
            case ANIMATE_STATE.SPREAD:
                tween = obj.transform.DOScale(a * 5 + 1, speed).SetEase(easePopIn);
                break;
            case ANIMATE_STATE.ROTATE_X:
                tween = obj.transform.DOLocalRotate(new Vector3(360 * (a - 0.5f), 0, 0), speed, RotateMode.FastBeyond360).SetEase(easePopIn);
                break;
            case ANIMATE_STATE.ROTATE_Y:
                tween = obj.transform.DOLocalRotate(new Vector3(0, 360 * (a - 0.5f), 0), speed, RotateMode.FastBeyond360).SetEase(easePopIn);
                break;
            case ANIMATE_STATE.ROTATE_Z:
                tween = obj.transform.DOLocalRotate(new Vector3(0, 0, 360 * (a - 0.5f)), speed, RotateMode.FastBeyond360).SetEase(easePopIn);
                break;
            case ANIMATE_STATE.MOVE_UP:
                tween = rectTrans.DOLocalMoveY(rectTrans.localPosition.y + screenHeight, speed).SetEase(easePopIn);
                break;
            case ANIMATE_STATE.MOVE_DOWN:
                tween = rectTrans.DOLocalMoveY(rectTrans.localPosition.y - screenHeight, speed).SetEase(easePopIn);
                break;
            case ANIMATE_STATE.MOVE_LEFT:
                tween = rectTrans.DOLocalMoveX(rectTrans.localPosition.x - screenWidth, speed).SetEase(easePopIn);
                break;
            case ANIMATE_STATE.MOVE_RIGHT:
                tween = rectTrans.DOLocalMoveX(rectTrans.localPosition.x + screenWidth, speed).SetEase(easePopIn);
                break;
            default:
                tween = obj.transform.DOScale(1, speed);
                break;
        }

        tween.SetId(this.gameObject);

        if (isFadeOutDisable)
        {
            tween.onComplete += () =>
            {
                gameObject.SetActive(false);
                if (this.callbackAction != null)
                {
                    this.callbackAction.Invoke();
                }
            };
        }
        else if (isFadeOutDestroy)
        {
            tween.onComplete += () =>
            {
                GameObject.Destroy(gameObject, 0.1f);
                //调用回调函数,只能调用一次
                if (this.callbackAction != null)
                {
                    this.callbackAction.Invoke();
                    this.callbackAction = null;
                }
            };
        }

    }

    /// <summary>
    /// 弹窗开始播放
    /// </summary>
    public void PopStart()
    {
        OnPlayAnimationIn();
    }

    /// <summary>
    /// 弹窗动画结束
    /// </summary>
    public void PopEnd()
    {
        OnPlayAnimationOut();
    }

    public void PopEnd(System.Action action)
    {
        this.callbackAction = action;
        OnPlayAnimationOut();
    }

    private void OnDestroy()
    {
        DOTween.Kill(this.gameObject);
    }


}
